import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * MyData数据仓库 Query By Example测试
 *
 * @author luohq
 * @date 2022-07-29 10:34
 */
public class MyDataRepositoryExampleTest  extends BaseTest {

    private static final Logger log = LoggerFactory.getLogger(MyDataRepositoryExampleTest.class);
    @Resource
    private MyDataRepository myDataRepository;



    @Test
    void testQueryByExample() {
        MyData myData = this.buildMyData(1L);
        //an exact match will be performed on all non-null properties
        //默认精准匹配所有非null属性（AND），等价于Example.of(myData, ExampleMatcher.matchingAll())
        //matchingAll表示and拼接
        //matchingAny表示or拼接
        Example<MyData> example = Example.of(myData);

        List<MyData> myDataList = this.myDataRepository.findAll(example);
        log.info("myDataList: {}", myDataList);
    }

    @Test
    void testQueryByExample_matcher() {
        MyData myData = this.buildMyData(1L);
        ExampleMatcher matcher = ExampleMatcher
                .matchingAll()
                //忽略大小写，可设置具体propertyPaths，若不设置propertyPaths则默认所有
                .withIgnoreCase("myName")
                //忽略匹配指定属性
                .withIgnorePaths("id");
        Example example = Example.of(myData, matcher);


        List<MyData> myDataList = this.myDataRepository.findAll(example);
        log.info("myDataList: {}", myDataList);
    }

    @Test
    void testQueryByExample_matcherProp() {
        MyData myData = this.buildMyData(1L);
        ExampleMatcher matcher = ExampleMatcher
                .matchingAll()
                //单独设置某一属性的匹配条件
                .withMatcher("myName", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase())
                .withMatcher("createBy", matcher1 -> matcher1.startsWith().ignoreCase())
                ;
        Example example = Example.of(myData, matcher);


        List<MyData> myDataList = this.myDataRepository.findAll(example);
        log.info("myDataList: {}", myDataList);
    }

    @Test
    void testQueryByExample_matcherAll() {
        MyData myData = this.buildMyData(1L);
        ExampleMatcher matcher = ExampleMatcher
                //matchAll - AND, matchAny - OR
                .matchingAll()

                //默认忽略null值属性，即不将null值属性拼接到条件中
                //.withIgnoreNullValues()

                //包含空值，即column is null
                //.withIncludeNullValues()

                //使用INCLUDE时会拼接id is null，而使用IGNORE则与withIgnoreNullValues类似
                //.withNullHandler(ExampleMatcher.NullHandler.INCLUDE|IGNORE)

                //设置String类型默认匹配逻辑（DEFAULT | EXACT | STARTING | ENDING | CONTAINING | REGEX）
                .withStringMatcher(ExampleMatcher.StringMatcher.EXACT)

                //转换属性值
                .withTransformer("myName", sourcePropOpt -> {
                    return sourcePropOpt.map(String.class::cast)
                            .map(myName -> {
                                return myName.concat("xxx");
                            });
                })
                .withTransformer("myType", sourcePropOpt -> sourcePropOpt.map(Integer.class::cast).map(myType -> myType + 100))

                //单独设置某一属性的匹配条件
                .withMatcher("myName", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase())
                .withMatcher("createBy", ExampleMatcher.GenericPropertyMatchers.startsWith().ignoreCase())
                ;
        Example example = Example.of(myData, matcher);


        List<MyData> myDataList = this.myDataRepository.findAll(example);
        log.info("myDataList: {}", myDataList);
    }


    //@Test
    //void testQueryByExample_queryDto() {
    //    MyDataQueryDto myDataQueryDto = this.buildMyDataQueryDto();
    //    Example<MyDataQueryDto> example = Example.of(myDataQueryDto);
    //    //提示类型不匹配
    //    this.myDataRepository.findAll(example);
    //}

    @SneakyThrows
    private MyData buildMyData(Long id) {
        MyData myData = new MyData();
        myData.setId(id);
        myData.setMyName("luo");
        myData.setMyType(2);
        myData.setCreateTime(DateUtil.parseDate("2022-07-13 19:40:56", "yyyy-MM-dd HH:mm:ss"));
        myData.setCreateBy("luo");
        return myData;
    }


    private MyDataQueryDto buildMyDataQueryDto() {
        MyDataQueryDto myDataQueryDto = new MyDataQueryDto();
        myDataQueryDto.setId(1L);
        myDataQueryDto.setMyName("lu");
        myDataQueryDto.setMyType(2);
        myDataQueryDto.setCreateTimeStart(DateUtil.stringToDate("2022-01-01 18:00:20"));
        myDataQueryDto.setCreateTimeEnd(new Date());
        return myDataQueryDto;
    }
}
